package cc.owoo.godpen.util;

import cc.owoo.godpen.structure.CustomLinkedList;

import java.util.Iterator;
import java.util.LinkedList;

/**
 * 路径处理工具类（非线程安全）
 * Created by nimensei
 * 2022-05-07 下午 07:39
 **/
public class Path implements Iterable<String> {
    private final CustomLinkedList<String> list = new CustomLinkedList<>();// 路径名称列表
    private String separator = "/";// 分隔符
    private boolean isFirstSeparator;// 头部是否有分隔符
    private boolean isLastSeparator;// 尾部是否有分隔符

    public Path() {
    }

    /**
     * 解析路径字符串
     *
     * @param path 路径字符串
     */
    public Path(String path) {
        set(path);
    }

    /**
     * 设置路径
     *
     * @param path 路径
     */
    public void set(Path path) {
        if (path == null)
            throw new NullPointerException("路径不能为空");
        list.clear();
        list.addAll(path.list);
        separator = path.separator;
        this.isFirstSeparator = path.isFirstSeparator;
        this.isLastSeparator = path.isLastSeparator;
    }


    /**
     * 重新设置路径
     */
    public void set(String path) {
        if (path == null)
            throw new NullPointerException("路径不能为空");
        if (path.length() == 0)
            return;
        isFirstSeparator = isLastSeparator = false;
        int before = 0;
        for (int i = 0; i < path.length(); i++) {
            char c = path.charAt(i);
            if (c != '/' && c != '\\')
                continue;
            if (i == 0) {
                isFirstSeparator = true;
                before = i + 1;
                continue;
            }
            if (i == before) {
                ++before;
                continue;
            }
            list.addLast(path.substring(before, i));
            before = i + 1;
        }
        if (path.length() == 1)
            return;
        if (before == path.length())
            isLastSeparator = true;
        else
            list.addLast(path.substring(before));
    }

    /**
     * 在路径的头部添加一个名称
     *
     * @param name 需要添加的名称
     */
    public void addFirstName(String name) {
        list.addFirst(name);
    }

    /**
     * 在路径的尾部添加一个名称
     *
     * @param name 需要添加的名称
     */
    public void addLastName(String name) {
        list.addLast(name);
    }

    /**
     * 获取第一个名称
     *
     * @return 路径名称
     */
    public String getFirstName() {
        return list.getFirst();
    }

    /**
     * 获取最后一个名称
     *
     * @return 路径名称
     */
    public String getLastName() {
        return list.getLast();
    }

    /**
     * 获取指定下标的路径名称
     *
     * @param index 名称下标
     * @return 元素名称
     */
    public String getName(int index) {
        return list.get(index);
    }

    /**
     * 删除头部路径名称
     *
     * @return 被删除的路径名称
     */
    public String removeFirstName() {
        return list.removeFirst();
    }

    /**
     * 删除尾部路径名称
     *
     * @return 被删除的路径名称
     */
    public String removeLastName() {
        return list.removeLast();
    }

    /**
     * 删除指定下标的路径名称
     *
     * @param index 需要删除的元素下标
     * @return 被删除的路径名称
     */
    public String removeName(int index) {
        return list.remove(index);
    }

    /**
     * 获取后缀名称，如果没有后缀，则返回默认null
     *
     * @return 后缀名称
     */
    public String getPostfix() {
        return getPostfix(null);
    }

    /**
     * 获取后缀名称
     *
     * @param defaultPostfix 如果没有后缀，则返回默认后缀
     * @return 后缀名称
     */
    public String getPostfix(String defaultPostfix) {
        return getPostfix(getLastName(), defaultPostfix);
    }

    /**
     * 获取后缀
     *
     * @param name           需要获取后缀的名称
     * @param defaultPostfix 如果没有后缀，则返回默认后缀
     * @return 后缀
     */
    public static String getPostfix(String name, String defaultPostfix) {
        int index = name.lastIndexOf('.');
        if (index == -1)
            return defaultPostfix;
        return name.substring(index);
    }

    /**
     * 判断最后一个路径名称的后缀
     *
     * @param postfix 需要判断的后缀
     * @return 是否为该后缀
     */
    public boolean isPostfix(String postfix) {
        if (size() == 0)
            return false;
        return getLastName().endsWith(postfix);
    }

    /**
     * 在尾部追加路径
     *
     * @param path 需要添加的路径
     */
    public void appendLast(Path path) {
        if (path == null)
            throw new NullPointerException("路径对象不能为空");
        if (path.list.size() == 0)
            return;
        if (list.size() == 0)
            isFirstSeparator = path.isFirstSeparator;
        list.addAll(path.list);
        isLastSeparator = path.isLastSeparator;
    }

    /**
     * 在头部追加路径
     *
     * @param path 需要添加的路径
     */
    public void appendFirst(Path path) {
        if (path == null)
            throw new NullPointerException("路径对象不能为空");
        if (path.list.size() == 0)
            return;
        if (list.size() == 0)
            isLastSeparator = path.isLastSeparator;
        isFirstSeparator = path.isFirstSeparator;
        var firstNode = path.list.getFirstNode();
        list.addFirst(firstNode.value());
        firstNode = firstNode.next();
        var node = list.getFirstNode();
        while (firstNode != null) {
            node = node.insertLast(firstNode.value());
            firstNode = firstNode.next();
        }
    }

    /**
     * 将元素添加到LinkedList中并返回
     *
     * @return 新创建的LinkedList
     */
    public LinkedList<String> toList() {
        LinkedList<String> list = new LinkedList<>();
        for (var node : this.list)
            list.add(node.value());
        return list;
    }

    /**
     * 序列化路径
     *
     * @return 序列化后的字符串
     */
    public String stringify() {
        return stringify(isFirstSeparator, isLastSeparator);
    }

    /**
     * 序列化路径
     *
     * @param isLeft  是否添加头部分隔符
     * @param isRight 是否添加尾部分隔符
     * @return 序列化后的字符串
     */
    public String stringify(boolean isLeft, boolean isRight) {
        StringBuilder stringBuilder = new StringBuilder();
        if (isLeft)
            stringBuilder.append(separator);
        for (var node : list) {
            if (node != list.getFirstNode())
                stringBuilder.append(separator);
            stringBuilder.append(node.value());
        }
        if (isRight)
            stringBuilder.append(separator);
        return stringBuilder.toString();
    }

    /**
     * 设置路径分隔符
     *
     * @param separator 路径分隔符
     */
    public void setSeparator(String separator) {
        if (separator == null)
            throw new NullPointerException("路径分隔符不能为空");
        this.separator = separator;
    }

    /**
     * 获取路径分隔符
     *
     * @return 路径分隔符
     */
    public String getSeparator() {
        return separator;
    }

    /**
     * 设置头部是否有分隔符
     *
     * @param firstSeparator 头部是否有分隔符
     */
    public void setFirstSeparator(boolean firstSeparator) {
        isFirstSeparator = firstSeparator;
    }

    /**
     * 设置尾部是否有分隔符
     *
     * @param lastSeparator 尾部是否有分隔符
     */
    public void setLastSeparator(boolean lastSeparator) {
        isLastSeparator = lastSeparator;
    }

    /**
     * 头部是否有分隔符
     *
     * @return 头部是否有分隔符
     */
    public boolean isFirstSeparator() {
        return isFirstSeparator;
    }

    /**
     * 尾部是否有分隔符
     *
     * @return 尾部是否有分隔符
     */
    public boolean isLastSeparator() {
        return isLastSeparator;
    }

    /**
     * 获取路径数量
     *
     * @return 路径数量
     */
    public int size() {
        return list.size();
    }

    /**
     * 复制路径
     *
     * @return 新的路径对象
     */
    public Path copy() {
        Path path = new Path();
        path.list.addAll(path.list);
        path.separator = separator;
        path.isFirstSeparator = isFirstSeparator;
        path.isLastSeparator = isLastSeparator;
        return path;
    }

    /**
     * 清空路径
     */
    public void clear() {
        list.clear();
        isFirstSeparator = isLastSeparator = false;
    }

    @Override
    public String toString() {
        return stringify();
    }

    @Override
    public Iterator<String> iterator() {
        var iterator = list.iterator();
        return new Iterator<String>() {
            @Override
            public boolean hasNext() {
                return iterator.hasNext();
            }

            @Override
            public String next() {
                return iterator.next().value();
            }
        };
    }
}
